﻿using OnlineEducation.Constants;
using OnlineEducation.Data;
using OnlineEducation.Helpers;
using OnlineEducation.Hubs;
using OnlineEducation.Models.ServerAPIModels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace OnlineEducation.Job
{
    internal class CreateMeetingJob : IJob, IDisposable
    {

        private readonly IServiceScopeFactory scopeFactory;

        private readonly ILogger _logger;

        private ApplicationDbContext _context;

        private readonly IWebHostEnvironment _hostingEnv;

        private readonly IHubContext<UpdateClassRoomStatus> _hubContext;

        private readonly string Job_Name = "CreateMeetingJob-";


        public CreateMeetingJob(IServiceScopeFactory scopeFactory,
            ILogger<CreateMeetingJob> logger,
            IHubContext<UpdateClassRoomStatus> hubContext,
            IWebHostEnvironment hostingEnv)
        {
            this.scopeFactory = scopeFactory;
            _hubContext = hubContext;
            _logger = logger;
            _hostingEnv = hostingEnv;
        }


        public void Dispose()
        {

        }

        public async Task Execute(IJobExecutionContext context)
        {
            using (var scope = scopeFactory.CreateScope())
            {
                _context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

                IConfiguration configuration= scope.ServiceProvider.GetRequiredService<IConfiguration>();

                var server_address = configuration.GetSection("BBB_Server_Address").Value;
                #region  
                try
                {

                    var meetingNo = context.JobDetail?.JobDataMap?.GetString("MeetingNo");

                    if (string.IsNullOrEmpty(meetingNo)) return;

                    //get lesson related info
                    var item = await _context.TeachingPlanItems.Include(n => n.TeachingPlan).ThenInclude(n => n.Course)
                        .Include(n => n.Lesson).Where(n => n.MeetingNo == meetingNo).FirstOrDefaultAsync();

                    var coursename = "";

                    if (item.TeachingPlan.Course == null)
                    {
                        coursename = item.TeachingPlan.Name;
                    }
                    else
                    {
                        coursename = item.TeachingPlan.Course.Title;
                    }

                    var name = coursename + " " + item.Lesson?.Chapter + "." + item.Lesson?.Section + " " + item.Lesson?.Title;

                    var createmeeting = new CreateMeeting
                    {
                        name = name,
                        meetingID = item.MeetingNo,
                        welcome = "欢迎参加" + name,
                        attendeePW = "111111",
                        moderatorPW = "222222",
                        //duration = 100,
                        copyright = "futureinfo",
                        muteOnStart = true,
                        allowModsToUnmuteUsers = true,
                        autoStartRecording = true,
                        logoutURL= "http://onlineeducation.futureinfo.cn",
                        meta_endCallbackUrl = "http://onlineeducation.futureinfo.cn/api/BBBCallback/EndMeetingCallback"
                    };
                    var param = Utility.CreateParams<CreateMeeting>(createmeeting, ServerAPI.Create);

                    var url = "";
                    if (item.Lesson == null)
                    {
                        url = item.TeachingPlan.MaterialURLs;
                    }
                    else
                    {
                        url = item.Lesson.MaterialURLs;
                    }


                    string xmlparameters = "<?xml version='1.0' encoding='UTF-8'?> <modules><module name='presentation'> <document url='http://onlineeducation.futureinfo.cn/" + url + "' /> </module></modules>";

                    var httprequest = HttpHelper.HttpPost($"{server_address}/bigbluebutton/api/create?" + param, xmlparameters);

                    var response = Utility.XMLToModel<CreateResponseEntity>(httprequest);

                    if (response.returncode == "SUCCESS")
                    {
                        _logger.LogInformation($"{Job_Name} {meetingNo} created successfully.");
                    }
                    else
                    {
                        _logger.LogInformation($"{Job_Name} {meetingNo} created unsuccessfully. response text is " + httprequest);

                        return;
                    }

                    item.Status = 1;//update status as started


                    _context.Update(item);

                    _logger.LogInformation($"{Job_Name} Update lesson {item.Id} as started.");

                    if (item.TeachingPlan.Status != 1)
                    {

                        item.TeachingPlan.Status = 1;// update status as started

                        _context.Update(item.TeachingPlan);

                        _logger.LogInformation($"{Job_Name} Update teaching plan {item.TeachingPlan.Id} as started.");
                    }


                    _context.SaveChanges();

                    //notify all client to update status
                    await _hubContext.Clients.All.SendAsync("ReceiveMessage", meetingNo, 1);

                    var expiredplanItems = _context.TeachingPlanItems
                        .Where(n => n.Status == 0).ToList().Where(n => DateTime.Now.Subtract(n.BeginTime).TotalSeconds > 1800).ToList();

                    foreach (var expiredplanItem in expiredplanItems)
                    {
                        expiredplanItem.Status = 2;//update status as done

                        _context.Update(expiredplanItem);

                        _logger.LogInformation($"{Job_Name} Update lesson {item.Id} as done because it expired.");
                    }
                    _context.SaveChanges();

                    foreach (var expiredplanItem in expiredplanItems)
                    {
                        //notify all client to update status
                        await _hubContext.Clients.All.SendAsync("ReceiveMessage", expiredplanItem.MeetingNo, 2);
                    }


                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message, ex.ToString());

                }
                #endregion

            }
        }
    }



}
